package com.coderside.fragment.arithmetic;

public class QuickSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {}


	public static void quickSort(int[] list, int low, int high) {
		int pivotpos; // 划分后的基准记录的位置
		if (low < high) {// 仅当区间长度大于1时才须排序
			pivotpos = Partition(list, low, high); // 对R[low..high]做划分
			quickSort(list, low, pivotpos - 1); // 对左区间递归排序
			quickSort(list, pivotpos + 1, high); // 对右区间递归排序
		}
	}

	private static int Partition(int[] list, int i, int j) {
		int pivot = list[i]; // 用区间的第1个记录作为基准
		while (i < j) { // 从区间两端交替向中间扫描，直至i=j为止
			while (i < j && list[j] >= pivot)
				// pivot相当于在位置i上
				j--; // 从右向左扫描，查找第1个关键字小于pivot.key的记录R[j]
			if (i < j) // 表示找到的R[j]的关键字<pivot.key
				list[i++] = list[j]; // 相当于交换R[i]和R[j]，交换后i指针加1
			while (i < j && list[i] <= pivot)
				// pivot相当于在位置j上
				i++; // 从左向右扫描，查找第1个关键字大于pivot.key的记录R[i]
			if (i < j) // 表示找到了R[i]，使R[i].key>pivot.key
				list[j--] = list[i]; // 相当于交换R[i]和R[j]，交换后j指针减1
		}
		list[i] = pivot; // 基准记录已被最后定位
		return i;
	}

	/**
	 * Swaps x[a] with x[b].
	 */
	private static void swap(int x[], int a, int b) {
		int t = x[a];
		x[a] = x[b];
		x[b] = t;
	}

	/**
	 * Returns the index of the median of the three indexed integers.
	 */
	private static int med3(int x[], int a, int b, int c) {
		return (x[a] < x[b] ? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
				: (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
	}

	/**
	 * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
	 */
	private static void vecswap(int x[], int a, int b, int n) {
		for (int i = 0; i < n; i++, a++, b++)
			swap(x, a, b);
	}

	/**
	 * Sorts the specified sub-array of integers into ascending order.
	 */
	private static void sort1(int x[], int off, int len) {
		// Insertion sort on smallest arrays
		if (len < 7) {
			for (int i = off; i < len + off; i++)
				for (int j = i; j > off && x[j - 1] > x[j]; j--)
					swap(x, j, j - 1);
			return;
		}

		// Choose a partition element, v
		int m = off + (len >> 1); // Small arrays, middle element
		if (len > 7) {
			int l = off;
			int n = off + len - 1;
			if (len > 40) { // Big arrays, pseudomedian of 9
				int s = len / 8;
				l = med3(x, l, l + s, l + 2 * s);
				m = med3(x, m - s, m, m + s);
				n = med3(x, n - 2 * s, n - s, n);
			}
			m = med3(x, l, m, n); // Mid-size, med of 3
		}
		int v = x[m];

		// Establish Invariant: v* (<v)* (>v)* v*
		int a = off, b = a, c = off + len - 1, d = c;
		while (true) {
			while (b <= c && x[b] <= v) {
				if (x[b] == v)
					swap(x, a++, b);
				b++;
			}
			while (c >= b && x[c] >= v) {
				if (x[c] == v)
					swap(x, c, d--);
				c--;
			}
			if (b > c)
				break;
			swap(x, b++, c--);
		}

		// Swap partition elements back to middle
		int s, n = off + len;
		s = Math.min(a - off, b - a);
		vecswap(x, off, b - s, s);
		s = Math.min(d - c, n - d - 1);
		vecswap(x, b, n - s, s);

		// Recursively sort non-partition-elements
		if ((s = b - a) > 1)
			sort1(x, off, s);
		if ((s = d - c) > 1)
			sort1(x, n - s, s);
	}

}
